package com.yunhe.history.service.data;

import com.yunhe.history.domain.data.ChargeAndDischargeCurve;
import com.yunhe.common.exception.ArgumentErrorException;
import com.yunhe.common.model.PageParam;
import com.yunhe.common.model.data.Measurement;
import com.yunhe.common.model.data.MeasurementDpuDTO;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;

/**
 * 量测Service
 * @author liuronglei
 */
public interface MeasurementService {

    /**
     * 新增量测对象
     * @param measurement 量测对象
     * @param frequency 时间频率
     */
    @Transactional
    Measurement createMeasurement(Measurement measurement,
                                  String frequency)
            throws ArgumentErrorException;

    /**
     * 批量新增量测对象
     * @param measurementList 量测对象列表
     * @param frequency 时间频率
     */
    @Transactional
    Iterable<Measurement> createMeasurement(List<Measurement> measurementList,
                                            String frequency)
            throws ArgumentErrorException;

    /**
     * 批量新增量测对象（异步方法）
     * @param measurementList 量测对象列表
     * @param frequency 时间频率
     */
    @Transactional
    Iterable<Measurement> createMeasurementAsync(List<Measurement> measurementList,
                                                 String frequency)
            throws ArgumentErrorException;

    /**
     * 新增DPU上传量测数据
     * @param measurementList
     */
    void createMeasurementFromDpuAsync(List<List<MeasurementDpuDTO>> measurementList) throws ArgumentErrorException;


    /**
     * 根据点号删除量测
     * @param pointNumber 点号
     * @param frequency 时间频率
     */
    @Transactional
    Long deleteByPointNumber(Long pointNumber,
                             String frequency);

    /**
     * 获得点号和量测列表对应的Map
     * @param pointNumbers 点号
     * @param dtime 时间
     * @param frequency 时间频率
     * @param flag 标记
     * @param fill 是否填充开始和结束时间
     */
    Map<Long, List<Measurement>> getMeasurementMap(List<Long> pointNumbers,
                                                   List<String> dtime,
                                                   String frequency,
                                                   Integer flag,
                                                   Boolean fill,
                                                   Boolean queryAllAfterDtime)
            throws ArgumentErrorException;

    /**
     * 获得点号和量测列表对应的Map（分片方式）
     * @param pointNumbers 点号
     * @param dtime 时间
     * @param frequency 时间频率
     * @param flag 标记
     */
    Map<Long, List<Measurement>> getMeasurementMapByShard(List<Long> pointNumbers,
                                                          List<String> dtime,
                                                          String frequency,
                                                          Integer flag,
                                                          Boolean fill)
            throws ArgumentErrorException;

    /**
     * 根据条件获得量测列表
     * @param pointNumber 点号
     * @param dtime 时间
     * @param frequency 时间频率
     * @param flag 标记
     * @param fill 是否填充开始和结束时间
     * @param pageParam 分页对象
     */
    Iterable<Measurement> findMeasurements(Long pointNumber,
                                           List<String> dtime,
                                           String frequency,
                                           Integer flag,
                                           Boolean fill,
                                           PageParam pageParam)
            throws ArgumentErrorException;

    /**
     * 根据条件获得量测列表
     * @param pointNumbers 点号列表
     * @param dtime 时间
     * @param frequency 时间频率
     * @param flag 标记
     * @param pageParam 分页对象
     */
    Iterable<Measurement> findMeasurements(List<Long> pointNumbers,
                                           List<String> dtime,
                                           String frequency,
                                           Integer flag,
                                           PageParam pageParam)
            throws ArgumentErrorException;

    void deleteMeasurements(Long pointNumber,
                            List<String> dtime,
                            String frequency,
                            Integer flag,
                            PageParam pageParam)
            throws ArgumentErrorException;


    /**
     * 获得从开始时间后的所有量测列表
     * @param pointNumber 点号
     * @param stateDate 开始时间
     * @param frequency 时间频率
     * @param flag 标记
     */
    Iterable<Measurement> findMeasurementsByStartDate(Long pointNumber,
                                                      String stateDate,
                                                      String frequency,
                                                      Integer flag);

    Iterable<Measurement> findMeasurementsEitherEnd(Long pointNumber,
                                                    List<String> dtime,
                                                    String frequency,
                                                    Integer flag);

    List<List<Measurement>> findMeasurementsEitherEnd(List<Long> pointNumber,
                                                      List<String> dtime,
                                                      String frequency,
                                                      Integer flag);

    /**
     * 获得点号最新的值
     * @param pointNumber 点号
     */
    Measurement findMeasurementsLast(Long pointNumber);


    /**
     * 批量获得点号最新的值
     * @param pointNumbers 点号
     * @param frequency 时间频率
     * @param flag 标记
     */
    Map<Long, Measurement> findMeasurementsLastBatch(List<Long> pointNumbers,
                                                     String frequency,
                                                     Integer flag,
                                                     String endTime);

//    Measurement findMeasurementsLastWithValue(Long pointNumber);
//
//    List<String> findPnWithoutValue(String dtime);

//    /**
//     * 获得指定点号和时间下的量测值
//     * @param pointNumber 点号
//     * @param dtime 时间
//     */
//    Measurement findCustomValue(Long pointNumber, String dtime) throws ObjectNotFoundException;

//    /**
//     * 获得点号的最新量测值
//     * @param pointNumber 点号
//     */
//    Measurement findLastValue(Long pointNumber) throws ObjectNotFoundException;

    /**
     * 根据点号获得点号与最后一次值不同的前一次的值
     * @param pointNumber 点号
     */
    Double getPreValue(Long pointNumber);

    Double getPreValue(Long pointNumber,
                       String dtime,
                       String frequency,
                       Integer flag);

    Map<Long, Double> getPreValues(List<Long> pointNumbers,
                                   Long rtime,
                                   String frequency,
                                   Integer flag);

    Measurement getNextMeasurement(Long pointNumber,
                                   String dtime,
                                   String frequency,
                                   Integer flag);

//    /**
//     * 根据点号和值获得第一次出现的时间
//     * @param pointNumber 点号
//     * @param value 点号值
//     */
//    String findFirstValueTime(Long pointNumber, Double value);

    /**
     * 计算点号在给定时间段的充电或者放电值
     * @param pointNumber
     * @return
     */
    ChargeAndDischargeCurve calcByIntegral(Long pointNumber, List<String> dates) throws ArgumentErrorException;


//    /**
//     * 根据设备、类型和端子获得点号
//     * @param deviceId 设备ID
//     * @param typeName 点号数据类型
//     * @param terminal 端子
//     */
//    Long getPointNumber(Long deviceId, String typeName, String terminal);


//    Long getPointNumber(Long deviceId, Long typeId) throws ObjectNotFoundException;
//
//    Long getPointNumber(Long deviceId, String typeName) throws ObjectNotFoundException;
//
//    Long getPointNumber(Long pointNumber) throws ObjectNotFoundException;

//    /**
//     * 根据点号获得量测对应
//     *
//     * @param pointNumber 点号
//     */
//    MeasurePointMap findMeasurePointMap(Long pointNumber);
//
//    /**
//     * 根据设备ID和类型ID获得量测对应
//     *
//     * @param devId  设备代码
//     * @param typeId 点号数据类型代码
//     */
//    MeasurePointMap findMeasurePointMapByDevAndType(Long devId, Long typeId, String typeName);
//
//    /**
//     * 根据点号列表获得量测对应列表
//     *
//     * @param pointNumberList 点号列表
//     */
//    List<MeasurePointMap> findMeasurePointMapList(List<Long> pointNumberList);

    /**
     * 根据条件获得一段时间内量测值最大的量测点
     * @param pointNumbers 点号列表
     * @param dtime 时间范围
     * @param frequency 时间频率
     * @param flag 标记
     */
    List<Measurement> getMaxMeasurement(List<Long> pointNumbers,
                                        List<String> dtime,
                                        String frequency,
                                        Integer flag) throws ArgumentErrorException;

    /**
     * 根据开始时间和结束时间获得量测值（没有对应时间点的数据，取上一个点）
     */
    List<List<Measurement>> findByStartAndEndTime(List<Long> pointNumbers, List<String> dtime, String frequency, Integer flag);
}
